package com.tbit.main.util.fuse;

/**
 * 熔断器管理类
 *
 * @Author:BUGTian
 * @DATE: 2021/10/25
 */
public class BreakerManager {
    /**
     * 超时时间
     */
    protected int timeout;
    /**
     * 失败次数
     */
    private int failureCount;
    /**
     * 连续成功次数
     */
    private int consecutiveSuccessCount;
    /**
     * 最大调用失败次数
     */
    private int failureThreshold;
    /**
     * 连续调用成功次数
     */
    private int consecutiveSuccessThreshold;
    /**
     * 当前熔断器状态
     */
    private AbstractBreakerState state;

    /**
     * Close状态下最大失败次数，HalfOpen状态下使用的最大连续成功次数，以及Open状态下的超时时间
     * 在初始状态下，熔断器切换到闭合状态
     *
     * @param failureThreshold            最大调用失败次数
     * @param consecutiveSuccessThreshold 连续调用成功次数
     * @param timeout                     超时时间
     */
    public BreakerManager(int failureThreshold, int consecutiveSuccessThreshold, int timeout) {
        if (failureThreshold < 1 || consecutiveSuccessThreshold < 1) {
            throw new RuntimeException("熔断器闭合状态的最大失败次数和半熔断状态的最大连续成功次数必须大于0！");
        }
        if (timeout < 1) {
            throw new RuntimeException("熔断器断开状态超时时间必须大于0！");
        }
        //参数赋值
        this.failureThreshold = failureThreshold;
        this.consecutiveSuccessThreshold = consecutiveSuccessThreshold;
        this.timeout = timeout;
        //切换到闭合状态
        moveToClosedState();
    }

    /**
     * 是否是闭合状态
     *
     * @return
     */
    public boolean isClosed() {
        return state instanceof CloseState;
    }

    /**
     * 是否是断开状态
     *
     * @return
     */
    public boolean isOpen() {
        return state instanceof OpenState;
    }

    /**
     * 是否是半断开状态
     *
     * @return
     */
    public boolean isHalfOpen() {
        return state instanceof HalfOpenState;
    }

    /**
     * 切换到闭合状态
     */
    protected void moveToClosedState() {
        state = new CloseState(this);
    }

    /**
     * 切换到断开状态
     */
    protected void moveToOpenState() {
        state = new OpenState(this);
    }

    /**
     * 切换到半断开状态
     */
    protected void moveToHalfOpenState() {
        state = new HalfOpenState(this);
    }

    /**
     * 失败次数加一
     */
    protected void increaseFailureCount() {
        failureCount++;
    }

    /**
     * 重置失败次数
     */
    protected void resetFailureCount() {
        failureCount = 0;
    }

    /**
     * 是否达到最大调用失败次数阈值
     *
     * @return
     */
    protected boolean failureThresholdReached() {
        return failureCount >= failureThreshold;
    }

    /**
     * 连续成功次数加一
     */
    protected void increaseSuccessCount() {
        consecutiveSuccessCount++;
    }

    /**
     * 重置连续成功次数
     */
    protected void resetConsecutiveSuccessCount() {
        consecutiveSuccessCount = 0;
    }

    /**
     * 是否达到连续调用成功次数阈值
     *
     * @return
     */
    protected boolean consecutiveSuccessThresholdReached() {
        return consecutiveSuccessCount >= consecutiveSuccessThreshold;
    }

    /**
     * 方法开始时调用
     */
    public void methodStart() {
        state.protectedCodeIsAboutToBeCalled();
    }

    /**
     * 方法结束时调用
     */
    public void methodEnd() {
        state.protectedCodeHasBeenCalled();
    }

    /**
     * 方法出现异常时调用
     */
    public void methodException() {
        state.ActUponException();
    }

}
